package com.zrt.utils.convert;


import java.util.Date;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.zrt.utils.date.DateUtil;

/**
 * JSON处理工具类
 *
 * @author 庄锐涛
 * @version 1.0.0
 * @since 1.2.0(alibaba fastjson)
 */
public class JsonUtils {

    private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class);

    /**
     * <pre>
     * 获取JSON字符串中某个整形属性值
     * </pre>
     */
    public static Integer getInt(final String jsonStr, final String key) {
        Integer _val = null;
        JSONObject jsonObject = parse(jsonStr);
        if (jsonObject != null) {
            _val = jsonObject.getInteger(key);
        }
        return _val;
    }

    /**
     * <pre>
     * 获取JSON字符串中某个长整型数据
     * <pre/>
     */
    public static Long getLong(final String jsonStr, final String key) {
        Long _val = null;
        JSONObject jsonObject = parse(jsonStr);
        if (jsonObject != null) {
            _val = jsonObject.getLong(key);
        }
        return _val;
    }

    /**
     * <pre>
     * 获取JSON字符串中某个长整数数据
     * <pre/>
     */
    public static long getLong(final String jsonStr, final String key, final long defaultVal) {
        Long _val = null;
        try {
            _val = getLong(jsonStr, key);
        } catch (Exception e) {
            logger.error("getInt方法异常,字符串={},属性名称={},defaultVal={},异常={}", jsonStr, key, defaultVal, e.getMessage());
        }
        if (_val == null) {
            return defaultVal;
        } else {
            return _val.intValue();
        }
    }

    /**
     * <pre>
     * 获取JSON字符串中某个整数属性值
     * </pre>
     */
    public static int getInt(final String jsonStr, final String key, final int defaultVal) {
        Integer _val = null;
        try {
            _val = getInt(jsonStr, key);
        } catch (Exception e) {
            logger.error("getInt方法异常,字符串={},属性名称={},defaultVal={},异常={}", jsonStr, key, defaultVal, e.getMessage());
        }
        if (_val == null) {
            return defaultVal;
        } else {
            return _val.intValue();
        }
    }

    /**
     * <pre>
     * 将前端传过来的json字符串转化为JsonObject对象
     * <pre/>
     */
    public static JSONObject parse(final String jsonStr) {
        if (isJsonString(jsonStr)) {
            return JSONObject.parseObject(jsonStr);
        }
        return null;
    }

    /**
     * 简单验证是否是正确的json字符串
     */
    public static boolean isJsonString(final String jsonStr) {
        boolean _val = true;
        if (StringUtils.isBlank(jsonStr)) {
            _val = false;
        } else {
            String str = StringUtils.trim(jsonStr);
            // 兼容前端传null或者undefined的错误对象错误字符串
            if (StringUtils.equalsAnyIgnoreCase(str, "null", "undefined")) {
                _val = false;
            }
        }
        return _val;
    }

    /**
     * <pre>
     * 将JSON字符串反序列化为指定返回对象
     * <pre/>
     */
    public static <T> T toObject(final String jsonStr, Class<T> clazz) {
        if (isJsonString(jsonStr) && clazz != null) {
            return JSONObject.parseObject(jsonStr, clazz);
        }
        return null;
    }

    /**
     * 将JSON字符串反序列化为指定返回类对象 <br/>
     * 注意:遇到格式化异常,不外抛,返回空对象
     *
     * @param jsonStr JSON字符串
     * @param clazz 指定返回类
     * @return 指定返回类对象
     */
    public static <T> T toObjectQuietly(final String jsonStr, final Class<T> clazz) {
        T result = null;
        try {
            result = toObject(jsonStr, clazz);
        } catch (Exception e) {
            logger.error("toObjectQuietly方法异常,jsonStr={},clazz={},异常={}", jsonStr, (clazz == null ? "" : clazz.getCanonicalName()), e.getMessage());
        }
        return result;
    }

    /**
     * <pre>
     * 将JSON字符串中的子属性反序列化为指定返回对象
     * 示例: jsonStr={"id":1,"city":{"id":222,"name":"222"}},使用toObject(jsonStr,"city",T.class)
     * </pre>
     *
     * @param jsonStr JSON字符串
     * @param key 子属性变量值
     * @param clazz 指定返回类
     * @retun 指定返回类对象
     */
    public static <T> T toObject(final String jsonStr, final String key, Class<T> clazz) {
        T obj = null;
        if (isJsonString(jsonStr) && clazz != null) {
            JSONObject jsonObject = JSON.parseObject(jsonStr);
            if (jsonObject != null) {
                JSONObject jsonObject1 = jsonObject.getJSONObject(key);
                if (jsonObject1 != null) {
                    obj = jsonObject1.toJavaObject(clazz);
                }
            }
        }
        return obj;
    }

    /**
     * 将JSON字符串中的子属性反序列化为指定返回类对象 <br/>
     * 示例: jsonStr={"id":1,"city":{"id":222,"name":"222"}}, 使用toObject(jsonStr,"city",T.class) <br/>
     * 注意:遇到格式化异常,不外抛,返回空对象
     *
     * @param jsonStr JSON字符串
     * @param key 子属性变量值
     * @param clazz 指定返回类
     * @return 指定返回类对象
     */
    public static <T> T toObjectQuietly(final String jsonStr, String key, final Class<T> clazz) {
        T result = null;
        try {
            result = toObject(jsonStr, key, clazz);
        } catch (Exception e) {
            logger.error("toObjectQuietly方法异常,jsonStr={},key={},clazz={},异常={}", jsonStr, key, (clazz == null ? "" : clazz.getCanonicalName()),
                    e.getMessage());
        }
        return result;
    }

    /**
     * <pre>
     * 将Json字符串反序列化为List
     * </pre>
     */
    public static <T> List<T> toList(String jsonStr, final Class<T> clazz) {
        if (isJsonString(jsonStr) && clazz != null) {
            return JSON.parseArray(jsonStr, clazz);
        }
        return null;
    }

    /**
     * 将Json字符串转换反序列化为List&lt;T&gt;对象<br/>
     * 注意:遇到格式化异常,不外抛,返回空对象<br/>
     *
     * @param jsonStr JSON字符串
     * @param clazz 指定返回类
     * @return 返回指定返回类对象列表, 校验不合规, 返回空值(非空列表)
     */
    public static <T> List<T> toListQuietly(String jsonStr, final Class<T> clazz) {
        List<T> result = null;
        try {
            result = toList(jsonStr, clazz);
        } catch (Exception e) {
            logger.error("toListQuietly方法异常,jsonStr={},clazz={},异常={}", jsonStr, (clazz == null ? "" : clazz.getCanonicalName()), e.getMessage());
        }
        return result;
    }

    /**
     * 将Json字符串的子属性反序列化为List&lt;T&gt;对象 <br/>
     * 示例: jsonStr={"id":1,"citys":[{"id":111,"name":"111"},{"id":222,"name":"222"}]}, 使用toObject(jsonStr,"citys",T.class)<br/>
     *
     * @param jsonStr JSON字符串
     * @param key 子属性变量值
     * @param clazz 指定返回类
     * @return 返回指定返回类对象列表, 校验不合规, 返回空值(非空列表)
     */
    public static <T> List<T> toList(String jsonStr, String key, final Class<T> clazz) {
        List<T> _val = null;
        if (isJsonString(jsonStr) && clazz != null) {
            JSONObject _jsonObject = JSON.parseObject(jsonStr);
            if (_jsonObject != null) {
                JSONArray _jsonArry = _jsonObject.getJSONArray(key);
                if (_jsonArry != null) {
                    _val = _jsonArry.toJavaList(clazz);
                }
            }
        }
        return _val;
    }

    /**
     * 将Json字符串反序列化为List&lt;T&gt;对象 <br/>
     * 示例: jsonStr={"id":1,"citys":[{"id":111,"name":"111"},{"id":222,"name":"222"}]}, 使用toObject(jsonStr,"citys",T.class)<br/>
     * 注意:遇到格式化异常,不外抛,返回空对象<br/>
     *
     * @param jsonStr JSON字符串
     * @param key 子属性变量值
     * @param clazz 指定返回类
     * @return 返回指定返回类对象列表, 校验不合规, 返回空值(非空列表)
     */
    public static <T> List<T> toListQuietly(String jsonStr, String key, final Class<T> clazz) {
        List<T> result = null;
        try {
            result = toList(jsonStr, key, clazz);
        } catch (Exception e) {
            logger.error("toListQuietly方法异常,jsonStr={},key={},clazz={},异常={}", jsonStr, key, (clazz == null ? "" : clazz.getCanonicalName()),
                    e.getMessage());
        }
        return result;
    }

    /**
     * <pre>
     * 获取JSON字符串中某个Date属性对象,仅包含日期<br/>
     * 注意:若属性字段不存在,返回null
     * 要求前端格式:"2019-05-23"
     * </pre>
     *
     * @param jsonStr JSON字符串
     * @param key 属性名称
     * @param defaultVal 默认值
     * @return Date属性对象, 如果属性值不存或为null, 则返回null
     */
    public static Date getDate(String jsonStr, String key, String formatterPattern, Date defaultVal) {
        String str = getString(jsonStr, key);
        if (str == null) {
            return defaultVal;
        }
        return DateUtil.parseToDate(formatterPattern, str);
    }

    /**
     * <pre>
     * 获取JSON字符串中某个字符串属性值
     * 注意: 字符串无法格式化,该方法会抛出异常
     * </pre>
     */
    public static String getString(final String jsonStr, final String key) {
        String _val = null;
        JSONObject jsonObject = parse(jsonStr);
        if (jsonObject != null) {
            _val = jsonObject.getString(key);
        }
        return _val;
    }

    /**
     * <pre>
     * 获取JSON字符串中某个字符串中属性值<br>
     * 注意:字符串无法格式化,异常不外抛,返回默认值<br/>
     * </pre>
     */
    public static String getString(final String jsonStr, final String key, String defaultVal) {
        String _val = null;
        try {
            _val = getString(jsonStr, key);
        } catch (Exception e) {
            logger.error("getString方法异常,字符串={},属性名称={},defaultVal={},异常={}", jsonStr, key, defaultVal, e.getMessage());
        }
        if (_val == null) {
            return defaultVal;
        } else {
            return _val;
        }
    }

}
